<template>
  <div>
    <audio ref="audio">
      <source :src="mp3Url">
    </audio>
    <n-space style="margin-bottom: 10px" justify="space-between">
      <n-space>
        <n-select  size="small" style="width: 150px" :options=keyWordExtractOptions v-model:value="extractOption">
        </n-select>
        <n-popconfirm
            @positive-click="gptImagesDescription"
        >
          <template #trigger>
            <n-button type="info" size="small">批量推理</n-button>
          </template>
          <n-checkbox v-model:checked="gptImagesDescriptionSkip">跳过已完成推理分镜？</n-checkbox>
        </n-popconfirm>
        <n-button size="small" type="info" @click="matchCharacter">标签匹配</n-button>
        <n-divider vertical></n-divider>
        <n-button size="small" type="primary" @click="initBatchOperationForm">批量出图</n-button>
        <n-button size="small"  type="primary" @click="viewOption.upscaleModalShow=true">批量放大</n-button>
        <n-divider vertical></n-divider>
      </n-space>

      <n-select
          size="small"
          style="width: 200px;"
          :options="storyBoardSelectType"
          v-model:value="storyBoardSelectOption"
          @update:value="getStoryBoardByChapterId">
      </n-select>
    </n-space>
    <n-grid :x-gap="5">
      <n-grid-item :span="24">
        <n-data-table
            v-if="option.characterOption"
            :size="'small'"
            :single-line="false"
            :columns="createColumns"
            :data="dataList.boardList"
            :bordered="false"
            :loading="tableLoading"
            :style="{ height: `${clientHeight - 150}px` }"
            flex-height
            class="table-align-start"
        />
        <n-space justify="end" style="margin-top: 10px">
          <n-pagination
              :display-order="['quick-jumper', 'pages', 'size-picker']"
              :item-count="tableTotal"
              :page-size="paginationReactive.pageSize"
              :page-sizes="paginationReactive.pageSizes"
              show-quick-jumper
              show-size-picker
              :on-update:page-size="onPageSizeChange"
              :on-update:page="onPageChange"
          />
        </n-space>
      </n-grid-item>
    </n-grid>
    <n-modal
        v-model:show="progressModal"
        class="custom-card"
        style="width: 500px"
        preset="card"
        title="任务进度"
        size="huge"
        :bordered="false"
        :mask-closable="false"
        @close="getStoryBoardByChapterId"
    >
      <n-space justify="space-around">
        <n-statistic label="当前进度" :value="currentTaskNum">
          <template #prefix>
          </template>
          <template #suffix>
            / {{ dataList.boardList.length }}
          </template>
        </n-statistic>

        <n-statistic label="成功/失败">
          <template #prefix>
            {{ taskStatus.successNum }}
          </template>
          <template #suffix>
            / {{ taskStatus.failNum }}
          </template>
        </n-statistic>
      </n-space>
      <n-progress
          type="line"
          :percentage=" Math.round(currentTaskNum/dataList.boardList.length*100) "
          :height="30"
          :border-radius="5"
          :fill-border-radius="0"
      />
    </n-modal>
    <n-modal
        v-model:show="addModalShow"
        style="width: 600px"
        preset="card"
        title="插入分镜"
        size="huge"
        :bordered="false"
    >
      <n-form>
        <n-h4>您当前在第
          <n-tag type="primary">{{ addNum }}</n-tag>
          分镜插入分镜,新增分镜编号为:
          <n-tag type="primary">{{ addNum + 1 }}</n-tag>
        </n-h4>
        <n-form-item label="原文">
          <n-input type="textarea" style="height: 100px;" v-model:value="editDataForm.content"></n-input>
        </n-form-item>
        <n-form-item label="关键词">
          <n-input type="textarea" style="height: 100px;" v-model:value="editDataForm.prompt"></n-input>
        </n-form-item>
      </n-form>
      <template #footer>
        <n-space justify="end">
          <n-button @click="addModalShow=false">取消</n-button>
          <n-button type="primary" @click="addOrUpdateBoard">确认</n-button>
        </n-space>
      </template>
    </n-modal>
    <n-modal
        v-model:show="updateModalShow"
        style="width: 800px"
        preset="card"
        title="分镜编辑"
        size="huge"
        :bordered="false"
    >
      <n-form>
        <n-row>
          <n-col span="11">
            <n-form-item label="原文描述">
              <n-input type="textarea" disabled style="height: 100px;"
                       v-model:value="editDataFrom_refer.content"></n-input>
            </n-form-item>
          </n-col>
          <n-col span="2">
            <n-space justify="center" style="margin-top: 50px">
              <n-icon :component="ArrowForwardOutline" size="30"></n-icon>
            </n-space>
          </n-col>
          <n-col span="11">
            <n-form-item label="原文描述">
              <n-input type="textarea" style="height: 100px;" v-model:value="editDataForm.content"></n-input>
            </n-form-item>
          </n-col>
        </n-row>
        <n-row>
          <n-col span="11">
            <n-form-item label="画面关键词">
              <n-input type="textarea" disabled style="height: 100px;"
                       v-model:value="editDataFrom_refer.prompt"></n-input>
            </n-form-item>
          </n-col>
          <n-col span="2">
            <n-space justify="center" style="margin-top: 50px">
              <n-icon :component="ArrowForwardOutline" size="30"></n-icon>
            </n-space>
          </n-col>
          <n-col span="11">
            <n-form-item label="画面关键词">
              <n-input type="textarea" style="height: 100px;" v-model:value="editDataForm.prompt"></n-input>
            </n-form-item>
          </n-col>
        </n-row>
        <n-row>
          <n-col span="11">
            <n-form-item label="关键词翻译">
              <n-input type="textarea" disabled style="height: 100px;"
                       v-model:value="editDataFrom_refer.promptEn"></n-input>
            </n-form-item>
          </n-col>
          <n-col span="2">
            <n-space justify="center" style="margin-top: 50px">
              <n-icon :component="ArrowForwardOutline" size="30"></n-icon>
            </n-space>
          </n-col>
          <n-col span="11">
            <n-form-item label="关键词翻译">
              <n-input type="textarea" style="height: 100px;" v-model:value="editDataForm.promptEn"></n-input>
            </n-form-item>
          </n-col>
        </n-row>
      </n-form>
      <template #footer>
        <n-space justify="end">
          <n-button @click="updateModalShow=false">取消</n-button>
          <n-button type="primary" @click="addOrUpdateBoard">确认</n-button>
        </n-space>
      </template>
    </n-modal>

    <n-modal v-model:show="imageModelShow" >
      <n-card
          title="骨骼图"
          style="width: 500px"
          :bordered="false"
          size="huge"
          role="dialog"
          aria-modal="true"
      >
        <SdAdvance :row="selectedBoard"></SdAdvance>
      </n-card>
    </n-modal>

    <n-modal
        v-model:show="viewOption.upscaleModalShow"
        :mask-closable=false
        :closable="true"
    >
      <UpscalerView
          :paintConfig="paintConfig"
          :resourceId="props.resourceId"
          :upsacleList="dataList.boardList"
          :closeFunction="upscalerViewClose"
          :storyId="props.storyId">
      </UpscalerView>
    </n-modal>

    <n-modal
        v-model:show="batchOperationForm.batchOperationModalShow"
        :mask-closable=false
    >
      <n-card
          style="width: 600px"
          title="自动任务"
          :bordered="false"
          size="huge">
        <n-form>
          <n-form-item label="任务类型">
            <n-radio-group v-model:value="batchOperationForm.batchOperationType">
              <n-radio value="1">仅生成图片</n-radio>

            </n-radio-group>
          </n-form-item>
          <n-grid x-gap="10">
            <n-grid-item :span="12">
              <n-form-item label="开始序号">
                <n-input-number
                    :precision="0"
                    v-model:value="batchOperationForm.batchOperationStartNum">
                </n-input-number>
              </n-form-item>
            </n-grid-item>
            <n-grid-item :span="12">
              <n-form-item label="结束序号">
                <n-input-number
                    :precision="0"
                    v-model:value="batchOperationForm.batchOperationEndNum">
                </n-input-number>
              </n-form-item>
            </n-grid-item>
            <n-grid-item :span="12">
              <n-form-item :show-label="false">
                <n-checkbox v-model:checked="skipFlag">跳过已完成</n-checkbox>
              </n-form-item>
            </n-grid-item>
            <n-grid-item :span="12">
              <n-form-item :show-label="false">
                <n-checkbox v-model:checked="runInBack">后台运行</n-checkbox>
              </n-form-item>
            </n-grid-item>
          </n-grid>
          <n-grid ref="progressGridRef" v-if="taskStatus.totalNum!=0">
            <n-grid-item :span="24">
              <n-space justify="space-around">
                <n-statistic label="当前进度" :value="currentTaskNum">
                  <template #prefix>
                  </template>
                  <template #suffix>
                    / {{ taskStatus.totalNum }}
                  </template>
                </n-statistic>
                <n-statistic label="成功/失败">
                  <template #prefix>
                    {{ taskStatus.successNum }}
                  </template>
                  <template #suffix>
                    /
                    <n-gradient-text type="error">{{ taskStatus.failNum }}</n-gradient-text>
                  </template>
                </n-statistic>
              </n-space>
            </n-grid-item>
            <n-grid-item :span="24">
              <n-progress
                  type="line"
                  :percentage=" Math.round((currentTaskNum/taskStatus.totalNum) * 100) "
                  :height="30"
                  :border-radius="5"
                  :fill-border-radius="0"
                  :indicator-placement="'inside'"
                  :processing="batchOperationForm.batchOperationFlag"
              />
            </n-grid-item>
          </n-grid>
        </n-form>

        <template #footer>
          <n-space justify="space-between">
            <n-button
                type="primary"
                @click="startTask"
                :loading="batchOperationForm.loading"
                v-if="!batchOperationForm.batchOperationFlag">开始任务
            </n-button>
            <n-button
                type="warning"
                v-if="!batchOperationForm.batchOperationFlag"
                @click="batchOperationForm.batchOperationModalShow = false">取消
            </n-button>
          </n-space>
          <n-button
              :block="true"
              type="error"
              style="margin-top:5px;"
              @click="shutDownTask"
              v-if="batchOperationForm.batchOperationFlag">终止任务
          </n-button>
        </template>
      </n-card>
    </n-modal>

    <n-drawer display-directive="show" v-model:show="viewOption.openPoseViewShow" :width="drawerWidth">
      <n-drawer-content title="从骨骼图选择" closable>
        <OpenPoseView mode="choseOpenPose" :choseOpenPose="chosenOpenPose"></OpenPoseView>
      </n-drawer-content>
    </n-drawer>
  </div>
</template>
<script setup lang="ts">
import {
  NButton, NIcon,
  NInput, NInputGroup, NPopconfirm,
  NRadio,
  NRadioGroup,
  NScrollbar,
  NSelect,
  NSpace,
  NTag,
  useMessage
} from 'naive-ui'
import {h, onMounted, reactive, ref} from "vue";
import {storyController} from "@/api/story/story.api";
import {storyBoardController} from "@/api/controller/story/storyBoard.api";
import {ArrowForwardOutline, CloseSharp,Move} from '@vicons/ionicons5'
import {storeToRefs} from "pinia";
import {useSystemStore} from "@/store/modules/useSystemStore";
import fileFunction from "@/libs/globalFunction/file";
import {VueDraggableNext} from "vue-draggable-next";
import {storySentenceController} from "@/api/controller/story/storySentenceController.api";
import OpenPoseView from '@/views/pages/configuration/openpose/index.vue'
import {v4 as uuidv4} from "uuid";
import Bus from "@/components/file/box/GlobalUploader/utils/bus";
import {promptControllerApi} from "@/api/prompt/prompt.api";
import {creatorDict} from "@/dictionary/creatorDict";
import {
  CaretForwardCircleSharp as CaretForwardCircleSharpIcon,
} from '@vicons/ionicons5'
import UpscalerView from "@/components/creator/function/upscaler.vue";
import PromptEdit from "@/views/pages/create/novel/components/storyboardcomp/promptEditNL.vue";
import PromptEditNormal from "@/views/pages/create/novel/components/storyboardcomp/promptEditTag.vue";
import PicEdit from "@/views/pages/create/novel/components/storyboardcomp/picEdit.vue";
import CharacterEdit from "@/views/pages/create/novel/components/storyboardcomp/characterEdit.vue";
import PicListEdit from "@/views/pages/create/novel/components/storyboardcomp/picListEdit.vue";
import SdAdvance from "@/views/pages/create/novel/components/storyboardcomp/sdAdvance.vue";


const {storyBoardSelectType} = creatorDict()
const message = useMessage()
const story = ref("")
const progressModal = ref(false)
const extractOption = ref('')
const tableLoading = ref(false)
const addOrUpdateLoading = ref(false)
const updateModalShow = ref(false)
const addModalShow = ref(false)
const addNum = ref(0)
const selectedBoard = ref(null)

const drawerWidth = ref(0)
const imageModelShow = ref(false)
const selectRow = ref(null)
const storyBoardSelectOption = ref("0")
const mp3Url = ref('')
const audio = ref(null)
const paintConfig = ref(null)
const promptType = ref(null)
const stopLoop = ref(false)
const skipFlag = ref(true)
const runInBack = ref(true)
const tableTotal = ref(0)
const gptImagesDescriptionSkip = ref(true)
const voiceRefreshKey = ref(0)
const weightOpen = ref(false)

const batchOperationForm = reactive({
  batchOperationType: '0',
  batchOperationLoading: false,
  batchOperationModalShow: false,
  batchOperationStartNum: 0,
  batchOperationEndNum: 0,
  batchOperationAppointFlag: false,
  batchOperationFlag: false,
  loading: false
})

const paginationReactive = reactive({
  page: 1,
  pageSize: 40,
  pageSizes: [40, 80, 120, 240]
})

// 当前推理的分镜
const currentTaskNum = ref(1)

// 任务状态
const taskStatus = ref({
  successNum: 0,
  failNum: 0,
  totalNum: 0
})


const option = ref({
  voiceOption: [],
  characterOption: [],
  sceneOption: [],
  angleOption: [],
  cameraOption: []
})

const dataList = ref({
  boardList: [],
  characterList: [],

})

const viewOption = ref({
  openPoseViewShow: false,
  upscaleModalShow: false
})



const {
  clientHeight,
  layoutHeaderHeight,
  darkTheme,
  tabsHeight
} = storeToRefs(useSystemStore());

const editDataFrom_refer = reactive({
  content: "",
  prompt: "",
  promptEn: ""
})

const editDataForm = reactive({
  id: "",
  chapterId: "",
  content: "",
  prompt: "",
  promptEn: "",
  orderNum: -1,
  characterName: ""
})


const props = defineProps({
  storyId: {
    type: String,
    required: true
  },
  resourceId: {
    type: String,
    required: true
  }
})


// 获取任务列表
const getSetUpOption = async () => {
  storyController.getSetUpInfo(props.storyId).then(res => {
    if (res.code === 200) {
      option.value.angleOption = res.data.angleOption
      option.value.cameraOption = res.data.cameraOption
      option.value.sceneOption = res.data.sceneOption
      option.value.characterOption = res.data.characterOption
    }
  })
}


const addBoard = (row: any) => {
  Object.keys(editDataForm).forEach(key => {
    editDataForm[key] = ''
  })
  addNum.value = row.orderNum
  editDataForm.orderNum = row.orderNum + 1
  editDataForm.chapterId = props.storyId
  addModalShow.value = true
}


const getStoryBoardByChapterId = () => {
  tableLoading.value = true
  const param = {
    storyId: props.storyId,
    page: paginationReactive.page,
    pageSize: paginationReactive.pageSize,
    type: storyBoardSelectOption.value
  }
  storyController.getVideoText(param).then(res => {
    if (res.code === 200) {
      tableTotal.value = res.data.total
      dataList.value.boardList = res.data.records
      // dataList.value.boardList = res.data
      dataList.value.boardList.forEach((item: any) => {
        if (item.characterName) {
          item.characterList = item.characterName.split(",")
        }

      })
    } else {
      message.error(res.msg)
    }
  }).finally(() => {
    tableLoading.value = false
  })
}


onMounted(async () => {
  await getStoryPaintConfig(props.storyId)
  await getSetUpOption()
  getStoryBoardByChapterId()
  getPromptOption()
  drawerWidth.value = window.innerWidth - 300
  window.addEventListener('resize', ev => {
    drawerWidth.value = window.innerWidth - 300;
  });
})






const deleteSentence = (sentence: any) => {
  // 找到分镜
  const storySentence = findSentences(sentence.storyBoardId)
  storySentence.splice(sentence.orderNum, 1)
  storySentenceController.deleteStorySentence(sentence).then(res => {
    if (res.code != 200) {
      message.error(res.msg)
    }else {
      storySentence.forEach((item: any, index: number) => {
        item.orderNum = index
      })
      updateSentences([sentence.storyBoardId], storySentence)
    }
  })
}


/***
 * 按下回车键,分镜内新增句子
 * @param item
 * @param event
 */
const handlerEnter = (item: any, event: any) => {
  const cursorPosition = event.target.selectionStart;
  const inputBeforeCursor = item.content.substring(0, cursorPosition);
  const inputAfterCursor = item.content.substring(cursorPosition);
  const sentences = findSentences(item.storyBoardId)
  const addSentences = {...item}
  addSentences.orderNum = addSentences.orderNum + 1
  addSentences.content = inputAfterCursor
  addSentences.id = uuidv4()
  for (let i = 0; i < sentences.length; i++) {
    const sentence = sentences[i];
    if (sentence.orderNum < item.orderNum) {
      continue
    }
    if (sentence.orderNum == item.orderNum) {
      sentences[i].content = inputBeforeCursor
    } else {
      sentence.orderNum = sentence.orderNum + 1
    }
  }
  sentences.push(addSentences)
  sentences.sort((a: any, b: any) => {
    return a.orderNum - b.orderNum
  })
  let storyBoardIdList = [item.storyBoardId]
  updateSentences(storyBoardIdList, sentences)
}


const findStoryBoard = (storyBoardId: string) => {
  for (let i = 0; i < dataList.value.boardList.length; i++) {
    if (dataList.value.boardList[i].id == storyBoardId) {
      return dataList.value.boardList[i]
    }
  }
}


/**
 * 根据分镜ID查询分镜的句子
 * @param storyBoardId
 */
const findSentences = (storyBoardId: string) => {
  for (let i = 0; i < dataList.value.boardList.length; i++) {
    if (dataList.value.boardList[i].id == storyBoardId) {
      return dataList.value.boardList[i].sentenceList
    }
  }
}

const onStorySentenceChange = (event: any) => {
  if (event.moved) {
    /**
     * 分镜内移动
     */
    let storyBoardIdList = []
    const storyBoardId = event.moved.element.storyBoardId
    storyBoardIdList.push(storyBoardId)
    const sentences = findSentences(storyBoardId)
    sentences.forEach((item: any, index: number) => {
      item.orderNum = index
    })
    updateSentences(storyBoardIdList, sentences)
  }
}

const updateSentences = (storyBoardIdList: any, sentenceList: any) => {
  const param = {
    sentences: sentenceList,
    storyBoardIdList: storyBoardIdList
  }
  storySentenceController.batchHandlerSentences(param).then(res => {
    if (res.code != 200) {
      message.error(res.msg)
    }
  })
}


const onStorySentenceAdd = () => {
  let storyBoardIdList = []
  let needToUpdateSentence = []
  let sentencesNeedToUpdate = findNeedToUpdateStoryBoard()
  sentencesNeedToUpdate.forEach(uniqueSet => {
    uniqueSet.forEach(value => {
      storyBoardIdList.push(value)
      let sentences = findSentences(value)
      for (let i = 0; i < sentences.length; i++) {
        let sentence = sentences[i]
        sentence.storyBoardId = value
        sentence.orderNum = i
        needToUpdateSentence.push(sentence)
      }
    })
  })
  updateSentences(storyBoardIdList, needToUpdateSentence)
}


const findNeedToUpdateStoryBoard = () => {
  return dataList.value.boardList.map(storyboard => {
    let uniqueSet = new Set(storyboard.sentenceList.map(item => item.storyBoardId));
    if (uniqueSet.size > 1) {
      return uniqueSet
    } else if (uniqueSet.size == 1 && storyboard.id != storyboard.sentenceList[0].storyBoardId) {
      uniqueSet.add(storyboard.id)
      return uniqueSet
    }
    return null; // 如果条件不满足，则返回null
  }).filter(result => result !== null);
}

const nextStep = (callback: any) => {
  storyController.checkStoryBoardPrompt(props.storyId).then(res => {
    if (res.code === 200) {
      callback(true)
    } else {
      message.error(res.data);
      callback(false)
    }
  })
}

const updateStorySentence = (storySentence: any) => {
  storySentenceController.addOrUpdateStorySentence(storySentence).then(res => {
    if (res.code != 200) {
      message.error(res.msg)
    } else {
      storySentence.isChange = '0'
    }
  })
}


const sentenceMerge = (sentence: any, type: string) => {
  const orderNum = sentence.orderNum
  const sentences = findSentences(sentence.storyBoardId)
  if (orderNum == 0 && type == 'up') {
    // 找到上一个分镜
    const storyBoard = findStoryBoard(sentence.storyBoardId)
    if (storyBoard.orderNum == 0) {
      message.error('无法向上合并了')
      return
    }
    let updateSentenceCollection = []
    const lastStoryBoard = dataList.value.boardList[storyBoard.orderNum - 1]
    const preSentences = lastStoryBoard.sentenceList
    // // // 找到合并的句子
    const preSentenceMerge = preSentences[preSentences.length - 1]
    preSentenceMerge.content = preSentenceMerge.content + sentence.content
    sentences.splice(orderNum, 1)
    sentences.forEach((item: any, index: number) => {
      item.orderNum = index
      updateSentenceCollection.push(item)
    })
    preSentences.forEach((item: any, index: number) => {
      item.orderNum = index
      updateSentenceCollection.push(item)
    })
    let storyBoardIdList = [lastStoryBoard.id, storyBoard.id]
    updateSentences(storyBoardIdList, updateSentenceCollection)
  } else if (orderNum == sentences.length - 1 && type == 'down') {
    const storyBoard = findStoryBoard(sentence.storyBoardId)
    if (storyBoard.orderNum == dataList.value.boardList.length - 1) {
      message.info('无法向下合并了')
      return
    }
    let updateSentenceCollection = []
    const nextStoryBoard = dataList.value.boardList[storyBoard.orderNum + 1]
    const nextSentences = nextStoryBoard.sentenceList
    // 找到合并的句子
    const nextSentenceMerge = nextSentences[0]
    nextSentenceMerge.content = sentence.content + nextSentenceMerge.content
    sentences.splice(orderNum, 1)
    sentences.forEach((item: any, index: number) => {
      item.orderNum = index
      updateSentenceCollection.push(item)
    })
    nextSentences.forEach((item: any, index: number) => {
      item.orderNum = index
      updateSentenceCollection.push(item)
    })
    let storyBoardIdList = [nextStoryBoard.id, storyBoard.id]
    updateSentences(storyBoardIdList, updateSentenceCollection)
  } else {
    // 分镜内合并
    if (type == 'up') {
      const preSentence = sentences[orderNum - 1]
      preSentence.content = preSentence.content + sentence.content
      sentences.splice(orderNum, 1)
    } else {
      const nextSentence = sentences[orderNum + 1]
      sentence.content = sentence.content + nextSentence.content
      sentences.splice(orderNum + 1, 1)
    }
    sentences.forEach((item: any, index: number) => {
      item.orderNum = index
    })
    let storyBoardIdList = [sentence.storyBoardId]
    updateSentences(storyBoardIdList, sentences)
  }
}

const updateBoard = (item: any) => {
  const param = {...item}
  delete param.characterList
  storyBoardController.addOrUpdateBoard(param).then(res => {
    if (res.code !== 200) {
      message.error(res.msg)
    }
  })
}

// 更新分镜信息
const addOrUpdateBoard = () => {
  addOrUpdateLoading.value = true
  storyBoardController.addOrUpdateBoard(editDataForm).then(res => {
    addOrUpdateLoading.value = false
    if (res.code === 200) {
      message.success(res.msg)
      getStoryBoardByChapterId()
      addModalShow.value = false
      updateModalShow.value = false
    } else {
      message.error(res.msg)
    }
  })
}


const chosenOpenPose = (openPose: any) => {
  selectedBoard.value.openPose = openPose.id
  selectedBoard.value.poseExampleBackground = openPose.poseExampleBackground
  selectedBoard.value.poseExampleImage = openPose.poseExampleImage
  updateBoard(selectedBoard.value)
  viewOption.value.openPoseViewShow = false
}

/**
 * 删除分镜
 * @param row
 */
const deleteBoard = (row: any) => {
  window.$dialog.warning({
    title: "温馨提醒",
    content: "是否继续删除第(" + row.orderNum + ")号分镜信息？",
    positiveText: "确定",
    negativeText: "取消",
    onPositiveClick: () => {
      storyBoardController.deleteBoard(row.id, row.chapterId).then(res => {
        if (res.code === 200) {
          message.success(res.msg)
          getStoryBoardByChapterId()
        } else {
          message.error(res.msg)
        }
      })
    }
  })
}


const gptImagesDescription = async () => {
  progressModal.value = true
  currentTaskNum.value = 0
  taskStatus.value = {
    successNum: 0,
    failNum: 0
  }
  for (const item of dataList.value.boardList) {
    currentTaskNum.value++
    console.log(item)
    if (gptImagesDescriptionSkip.value) {
      if (item.prompt != null && item.prompt.length > 0) {
        taskStatus.value.successNum++
        continue;
      }
    }
    delete item.characterList
    item.content = item.sentenceList.map((item: any) => item.content).join("\n")
    if (!item.content) {
      taskStatus.value.failNum++
      continue
    }
    try {
      const res = await storyController.getImageDescription(item, extractOption.value)
      if (res.code === 200) {
        // 成功
        taskStatus.value.successNum++
      } else {
        // 失败
        taskStatus.value.failNum++
      }
    } catch (e) {
      taskStatus.value.failNum++
    }
  }
  getStoryBoardByChapterId()
}

const gptImageDescription = (row: any) => {
  const storyBorad = {...row}
  row.loading = true
  delete storyBorad.characterList
  row.content = row.sentenceList.map((item: any) => item.content).join("\n")
  if (!row.content) {
    message.error("分镜内容为空")
    row.loading = false
    return
  }
  storyController.getImageDescription(storyBorad, extractOption.value).then(res => {
    if (res.code === 200) {
      // getStoryBoardByChapterId()
      if (res.data){
        row.prompt = res.data.prompt
      }
    } else {
      message.error(res.msg)
    }
  }).finally(() => {
    row.loading = false
  })
}


const updateSentence = (item: any) => {
  updateStorySentence(item)
}

defineExpose({
  nextStep
})


/**
 * 获取该章节的绘画配置
 * @param chapterId
 */
const getStoryPaintConfig = async (chapterId: string) => {
  try {
    const res = await storyController.getStoryPaintConfig(chapterId);
    if (res.code === 200) {
      if (res.data != null) {
        paintConfig.value = JSON.parse(res.data.paintConfigText)
        promptType.value = res.data.promptType
      }
    } else {
      message.error(res.msg);
    }
  } catch (error) {
    console.error(error);
  }
}

Bus.on('refreshStoryConfig', () => {
  getStoryPaintConfig(props.storyId)
  getSetUpOption()
  voiceRefreshKey.value++
  getStoryBoardByChapterId()
})


Bus.on('updateStoryBoardTaskStatus',(taskStatusInfo:any)=>{
  if (taskStatusInfo?.storyId==props.storyId){
    updateImageStatus(taskStatusInfo)
  }
})

const updateImageStatus = (taskStatusInfo:any) => {
  // console.log(storyId)
  dataList.value.boardList.forEach((item: any) => {
    item.buttonLoading = false
    item.audioButtonLoading = false
    taskStatusInfo.inProgressStoryBoardNum.forEach((num: any) => {
      if (item.orderNum == num) {
        item.buttonLoading = true
      }
    })
  })

  taskStatusInfo.inProgressVoiceNum.forEach((num: any) => {
    dataList.value.boardList.forEach((item: any) => {
      if (item.orderNum == num) {
        item.audioButtonLoading = true
      }
    })
  })

  let updateOrderNum = []

  taskStatusInfo.finishedVoiceNum.forEach((num: any) => {
    updateOrderNum.push(num)
  })

  taskStatusInfo.finishedStoryBoardNum.forEach((num: any) => {
    if (updateOrderNum.indexOf(num) == -1) {
      updateOrderNum.push(num)
    }
  })

  updateStoryBoardByNum(updateOrderNum)
}



const updateStoryBoardByNum = (orderNum:any)=>{
  if (orderNum.length==0){
    return
  }
  const data = {
    storyId: props.storyId,
    orderNums: orderNum
  }
  storyBoardController.updateByOrderNum(data).then(res => {
    if (res.code === 200) {
      res.data.forEach((item: any) => {
        dataList.value.boardList.forEach((board: any) => {
          if (board.id == item.id) {
            board.imageUrl = item.imageUrl
            board.imageList = item.imageList
            board.audioUrl = item.audioUrl
          }
        })
      })
    }
  })
}



const keyWordExtractOptions = ref([])
const getPromptOption = () => {
  promptControllerApi.getGptPromptOption('custom_keyword').then(res => {
    if (res.code === 200) {
      console.log(res.data)
      if (res.data) {
        keyWordExtractOptions.value = res.data.map((item: any) => {
          return {
            label: item.promptTitle,
            value: item.id
          }
        })
        keyWordExtractOptions.value.unshift({
          label: 'EasyAI推理大师',
          value: '888'
        })

        keyWordExtractOptions.value.unshift({
          label: 'EasyAI推理大师-省流版',
          value: '999'
        })
        extractOption.value = keyWordExtractOptions.value[0].value
      }
    }
  })
}


const reTts = async (row: any) => {
  row.audioButtonLoading = true
  const res = await storyBoardController.reTtsStoryBoardAndCheck(row.id, 30 * 1000).catch(res => {
    message.error("系统异常,请稍后再试")
  }).finally(() => {
    row.audioButtonLoading = false
  })
  if (res.taskStatus === 'SUCCESS') {
    row.audioUrl = res.userFileId
  }
}


const upscalerViewClose = () => {
  viewOption.value.upscaleModalShow = false
  getStoryBoardByChapterId()
}

const initBatchOperationForm = () => {
  batchOperationForm.batchOperationType = '1'
  batchOperationForm.batchOperationStartNum = 0
  batchOperationForm.batchOperationEndNum = dataList.value.boardList.length - 1
  batchOperationForm.batchOperationAppointFlag = false
  batchOperationForm.batchOperationModalShow = true
  taskStatus.value.totalNum = 0
  taskStatus.value.successNum = 0
  taskStatus.value.failNum = 0
}

const startTask = async () => {
  if (runInBack.value) {
    const param = {
      operationType: batchOperationForm.batchOperationType,
      storyId: props.storyId,
      skipFlag: skipFlag.value,
      startNum: batchOperationForm.batchOperationStartNum,
      endNum: batchOperationForm.batchOperationEndNum
    }
    batchOperationForm.loading = true
    storyController.startStoryBatchTask(param).then(res => {
      if (res.code === 200) {
        window.$message.success("任务已提交")
      }
    }).finally(() => {
      batchOperationForm.loading = false
      batchOperationForm.batchOperationModalShow = false
    })
  } else {
    stopLoop.value = false
    currentTaskNum.value = 0
    taskStatus.value = {
      successNum: 0,
      failNum: 0,
      totalNum: batchOperationForm.batchOperationEndNum - batchOperationForm.batchOperationStartNum + 1
    }
    batchOperationForm.batchOperationFlag = true
    for (let i = batchOperationForm.batchOperationStartNum;
         i <= batchOperationForm.batchOperationEndNum;
         i++) {
      if (stopLoop.value) {
        break
      }
      currentTaskNum.value++
      const item = dataList.value.boardList[i]
      if (batchOperationForm.batchOperationType === '0' || batchOperationForm.batchOperationType === '1') {
        if (skipFlag.value) {
          if (item.imgFileId != null && item.imgFileId.length > 0) {
            // 跳过
            taskStatus.value.successNum++
            continue
          }
        }
        // 开启绘画任务
        try {
          if (batchOperationForm.batchOperationType === '0') {
            // 同步发送
            await storyController.reTtsStoryBoard(item.id)
          }
          const res = await storyBoardController.rePaintStoryBoardAndCheck(item.id, 1.5 * 60 * 1000)
          if (res.taskStatus === 'SUCCESS') {
            // 成功
            taskStatus.value.successNum++
          } else {
            // 失败
            taskStatus.value.failNum++
          }
        } catch (e) {
          taskStatus.value.failNum++
        }
      } else {
        try {
          if (skipFlag.value) {
            if (item.audioFileId != null && item.audioFileId.length > 0) {
              // 跳过
              taskStatus.value.successNum++
              continue
            }
          }
          const res_tts = await storyBoardController.reTtsStoryBoardAndCheck(item.id, 30 * 1000)
          if (res_tts.taskStatus === 'SUCCESS') {
            // 成功
            taskStatus.value.successNum++
          } else {
            // 失败
            taskStatus.value.failNum++
          }
        } catch (e) {
          taskStatus.value.failNum++
        }
      }
    }
    // batchOperationForm.batchOperationModalShow = false
    batchOperationForm.batchOperationFlag = false
    // 重载数据
    getStoryBoardByChapterId()
  }
}


const shutDownTask = () => {
  window.$dialog.warning({
    title: "提示",
    content: "是否停止任务?",
    positiveText: "确认",
    negativeText: "取消",
    onPositiveClick: () => {
      stopLoop.value = true
      batchOperationForm.batchOperationFlag = false
      batchOperationForm.batchOperationModalShow = false
    }
  })
}

const imageSelected = (userFileId: string) => {
  selectRow.value.imageUrl = userFileId
  console.log(userFileId)
}


const onPageSizeChange = (pageSize: number) => {
  paginationReactive.pageSize = pageSize
  getStoryBoardByChapterId()
  getPromptOption()
}

const onPageChange = (page: number) => {
  paginationReactive.page = page
  getStoryBoardByChapterId()
  getPromptOption()
}

const characterChecked = (e: any, item: any) => {
  if(item.characterList && item.characterList.length >2){
    item.characterList = item.characterList.slice(0,2)
    window.$message.warning('最多选择两个角色')
    return false
  }
  const ids = option.value.characterOption.filter((character: any) => {
    if (e.includes(character.id)) {
      return true
    }
  })
  if (ids.length > 2) {
    return false;
  }
  const characterNames = []
  for (let i = 0; i < ids.length; i++) {
    characterNames.push(ids[i].id)
  }
  item.characterName = characterNames.join(",")
  updateBoard(item)
}

const matchCharacter = () => {
  storyController.matchCharacter(props.storyId).then(res => {
    if (res.code === 200){
      message.success(res.msg)
      getStoryBoardByChapterId()
    }else {
      message.error(res.msg)
    }
  })
}

// 列表字段
const createColumns = [
  {
    title: '操作',
    titleAlign: 'center',
    width: 80,
    align: 'center',
    fixed: 'left',
    render (row) {
      let functionButton =
          [h(NSpace,{justify: 'center'},{default: () => '第'+row.orderNum+'镜'}), h(
              NButton,
              {
                size: 'small',
                block: true,
                type: 'warning',
                loading: row.loading,
                onClick: () => gptImageDescription(row)
              },
              { default: () => '推理分镜'}
          ), h(
              NButton,
              {
                size: 'small',
                block: true,
                type: 'warning',
                style: 'margin-top:5px;',
                onClick: () => { selectedBoard.value = row; imageModelShow.value = true}
              },
              { default: () =>  row.openPose? '骨骼图 - 1':'骨骼图'}
          ) , h(
              NButton,
              {
                size: 'small',
                block: true,
                type: 'info',
                style: 'margin-top:5px;',
                onClick: () => addBoard(row)
              },
              { default: () => '插入分镜'}
          ), h(
              NButton,
              {
                size: 'small',
                block: true,
                type: 'info',
                style: 'margin-top:5px;',
                onClick: () => deleteBoard(row)
              },
              { default: () => '删除分镜'})
          ]

      return functionButton
    }
  },
  {
    title: '原文描述',
    titleAlign: 'center',
    key: 'content',
    width: 400,
    fixed: 'left',
    render(row:any, index:any) {
      return h(NScrollbar, {
        style: 'height: 200px; overflow-y: auto',
        trigger: 'none'
      }, {
        default: () =>
            h(VueDraggableNext, {
              list: row.sentenceList,
              group: 'storySentence',
              animation: 200,
              handle: '.handle',
              onAdd: () => onStorySentenceAdd(),
              onChange: (event: any) => onStorySentenceChange(event),
              onEnd: (event: any) => onStorySentenceChange(event)
            }, {
              default: () => row.sentenceList.map((item: any, index: any) => {
                return h(NInputGroup, {
                  class: 'story-sentence',
                  style: 'margin-bottom: 2px;'
                }, [
                  h(NButton, {
                        type: 'info',
                        size:'small',
                        class: 'handle'
                      },
                      {default: () => h(NIcon, {},{default: () => h(Move)})}),
                  h(NInput, {
                    value: item.content,
                    size: 'small',
                    style: 'width: 80%;',
                    onKeydown: (event: any) => {
                      if (event.key=='Enter'){
                        handlerEnter(item, event)
                      }
                    },
                    onUpdateValue (v) {
                      item.content = v
                      updateSentence(item)
                    }
                  }),
                  h(
                      NPopconfirm,
                      {
                        onPositiveClick: () => deleteSentence(item)
                      },
                      {
                        trigger: () =>
                            h(
                                NButton,
                                {
                                  size: 'small',
                                  type: 'warning'
                                },
                                {
                                  default: () =>
                                      h(
                                          NIcon,
                                          null,
                                          {
                                            default: () =>  h(CloseSharp)
                                          }
                                      )
                                }
                            ),
                        default: () => '确定删除该句内容吗？'
                      }
                  ),
                ])
              })
            })
      })
    }
  },
  {
    title: '画面关键字',
    key: 'prompt',
    titleAlign: 'center',
    width:400,
    titleAlign:'center',
    render(row:any, index:any) {
      if (promptType.value == 'normal'){
        return h(PromptEditNormal,{
          row:row,
          weightOpen:weightOpen.value
        })
      }else{
        return h(PromptEdit,{
          row:row,
          weightOpen:weightOpen.value
        })
      }
    }
  }, {
    title: '人物信息',
    key: 'prompt',
    titleAlign: 'center',
    width: 150,
    render(row:any, index:any) {
      return h(CharacterEdit,{
        row:row,
        characterOptions: option.value.characterOption
      })
    }
  },{
    title: '图片',
    key: 'character',
    titleAlign:'center',
    width: 200,
    render(row:any, index:any) {
      return h(PicEdit,{
        row:row,
        updateStoryBoardByNum: updateStoryBoardByNum
      })
    }
  },{
    title: '图片集',
    key: 'character',
    titleAlign:'center',
    width: 200,
    render(row:any, index:any) {
      return h(PicListEdit,{
        row:row,
        updateStoryBoardByNum: updateStoryBoardByNum
      })
    }
  }
]

</script>
<style scoped>
.table-align-start th,
.table-align-start td {
  text-align: start;
}
</style>
